/**
 * @p.md
 * 
 * PersistentActor 类实现了 Persistent 接口，提供持久化 Actor 的基本功能。
 * 派生类只需覆盖 persistenceId、receiveRecover 和 receiveCommand 方法。
 */
import { Actor } from '../actor/actor';
import { Context } from '../actor/context';
import { 
  CommandContext, 
  EventType, 
  Persistent, 
  PersistentContext, 
  RecoverContext,
  SnapshotSelectionCriteria,
  EventSelectionCriteria
} from './persistent';
import { PID } from '../actor/pid';

// 扩展 EventType 枚举值，增加 RecoveryCompleted
// 这应该在 persistent.ts 中定义，这里为了修复错误临时添加
enum ExtendedEventType {
  RecoveryCompleted = 'RecoveryCompleted'
}

/**
 * 持久化 Actor 基类，支持事件持久化和状态恢复
 */
export abstract class PersistentActor implements Actor, Persistent {
  /**
   * 持久化上下文
   */
  private persistentContext?: PersistentContext;
  
  /**
   * 恢复完成标志
   */
  private recoveryCompleted: boolean = false;
  
  /**
   * 获取唯一的持久化标识符
   */
  abstract get persistenceId(): string;
  
  /**
   * 处理恢复的事件和快照
   * @param context 恢复上下文
   */
  abstract receiveRecover(context: RecoverContext): void;
  
  /**
   * 处理命令
   * @param context 命令上下文
   */
  abstract receiveCommand(context: CommandContext): void;
  
  /**
   * 接收消息并根据恢复状态决定处理方式
   * @param context Actor 上下文
   */
  receive(context: Context): void {
    // 类型转换，需确保实际运行时提供的是持久化上下文
    this.persistentContext = context as unknown as PersistentContext;
    
    // 处理恢复消息
    if (!this.recoveryCompleted) {
      // 检查消息类型
      const message = context.message();
      const messageType = message && typeof message === 'object' ? (message as any).type : undefined;
      
      if (messageType === ExtendedEventType.RecoveryCompleted) {
        this.recoveryCompleted = true;
        this.onRecoveryCompleted(this.persistentContext);
        return;
      }
      
      // 恢复过程中的消息处理
      // 运行时类型检查 - 假设上下文同时实现了 PersistentContext 和 RecoverContext
      const recoverCtx = context as unknown as (PersistentContext & RecoverContext);
      if (recoverCtx.event !== undefined && recoverCtx.eventType !== undefined) {
        this.receiveRecover(recoverCtx);
      }
    } else {
      // 恢复完成后处理命令
      // 运行时类型检查 - 假设上下文同时实现了 PersistentContext 和 CommandContext
      const cmdCtx = context as unknown as CommandContext;
      if ('index' in cmdCtx) {
        this.receiveCommand(cmdCtx);
      }
    }
  }
  
  /**
   * 当恢复完成时调用
   * @param context 持久化上下文
   */
  protected onRecoveryCompleted(context: PersistentContext): void {
    // 默认实现为空，子类可以覆盖
  }
  
  /**
   * 持久化事件
   * @param event 事件数据
   * @returns 返回 Promise
   */
  protected persist(event: any): Promise<void> {
    if (!this.persistentContext) {
      throw new Error('PersistentContext is not available');
    }
    
    return this.persistentContext.persist(event);
  }
  
  /**
   * 持久化多个事件
   * @param events 事件数组
   * @returns 返回 Promise
   */
  protected persistAll(events: any[]): Promise<void> {
    if (!this.persistentContext) {
      throw new Error('PersistentContext is not available');
    }
    
    return this.persistentContext.persistAll(events);
  }
  
  /**
   * 创建快照
   * @param snapshot 快照数据
   * @returns 返回 Promise
   */
  protected createSnapshot(snapshot: any): Promise<void> {
    if (!this.persistentContext) {
      throw new Error('PersistentContext is not available');
    }
    
    // 调用上下文的保存快照方法
    return this.persistentContext.snapshot(snapshot);
  }
  
  /**
   * 删除快照
   * @param criteria 快照选择条件
   * @returns 返回 Promise
   */
  protected deleteSnapshots(criteria: SnapshotSelectionCriteria): Promise<void> {
    if (!this.persistentContext) {
      throw new Error('PersistentContext is not available');
    }
    
    return this.persistentContext.deleteSnapshots(criteria);
  }
  
  /**
   * 删除事件
   * @param criteria 事件选择条件
   * @returns 返回 Promise
   */
  protected deleteEvents(criteria: EventSelectionCriteria): Promise<void> {
    if (!this.persistentContext) {
      throw new Error('PersistentContext is not available');
    }
    
    return this.persistentContext.deleteEvents(criteria);
  }
} 